package main

import (
	"fmt"
	"github.com/jung-kurt/gofpdf"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"
	"sync"
)

func unzip(zipPath, outputPath string) error {
	cmd := exec.Command("unzip", zipPath, "-d", outputPath)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func convertTIFtoPNG(dirPath string) error {
	tifFiles, err := filepath.Glob(filepath.Join(dirPath, "*.tif"))
	if err != nil {
		return err
	}

	var wg sync.WaitGroup
	var mu sync.Mutex                        // 用于保护 fmt.Printf，确保不会乱序输出
	errCh := make(chan error, len(tifFiles)) // 用于传递错误信息的通道

	for _, tifFile := range tifFiles {
		wg.Add(1)
		go func(tifFile string) {
			defer wg.Done()
			pngFile := strings.TrimSuffix(tifFile, ".tif") + ".png"
			cmd := exec.Command("convert", tifFile, pngFile)
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			err := cmd.Run()

			// 使用互斥锁确保 fmt.Printf 不会乱序输出
			mu.Lock()
			defer mu.Unlock()

			if err != nil {
				errCh <- fmt.Errorf("将 %s 转换为 %s 时出错: %w", tifFile, pngFile, err)
			}
			fmt.Printf("已将 %s 转换为 %s\n", tifFile, pngFile)
		}(tifFile)
	}
	// 启动一个 goroutine 用于关闭错误通道
	go func() {
		wg.Wait()
		close(errCh)
	}()

	wg.Wait()

	// 检查错误通道是否有错误
	f, err := os.OpenFile("error.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	// 检查错误通道是否有错误
	for err := range errCh {
		if err != nil {
			// 可以在这里处理错误，例如输出日志或者执行其他操作
			fmt.Println(err)
			// 将错误信息写入 error.log 文件
			if _, err := fmt.Fprintf(f, "%v\n", err); err != nil {
				return err
			}
		}
	}
	return nil
}

func readAndSortPNGs(dirPath string) ([]string, error) {
	files, err := ioutil.ReadDir(dirPath)
	if err != nil {
		return nil, err
	}

	var pngFiles []string
	for _, file := range files {
		if strings.HasSuffix(file.Name(), ".png") {
			pngFiles = append(pngFiles, filepath.Join(dirPath, file.Name()))
		}
	}
	// 按文件名排序
	sort.Strings(pngFiles)
	return pngFiles, nil
}

func createPDF(pdfPath string, imagePaths []string) error {
	// 计算缩放比例
	targetWidth := 210  // A4宽度（毫米）
	targetHeight := 297 // A4高度（毫米）
	//targetDPI := 300

	// 设置图像在PDF中的位置和大小
	x := 10.0 // 调整x坐标以使图像居中
	y := 10.0
	width := float64(targetWidth) - 20.0   // 调整宽度以使图像居中
	height := float64(targetHeight) - 20.0 // 调整高度以使图像居中

	// 创建PDF文档
	pdf := gofpdf.New("P", "mm", "A4", "") // 使用A4大小

	count := len(imagePaths)
	for index, imagePath := range imagePaths {

		// 添加页面
		pdf.AddPage()
		// 将图像插入PDF
		pdf.ImageOptions(imagePath, x, y, width, height, false, gofpdf.ImageOptions{ReadDpi: true}, 0, "")

		// 添加页面
		addPageNumber(pdf, index, count)
	}

	// 输出 PDF 文件
	return pdf.OutputFileAndClose(pdfPath)
}

func addPageNumber(pdf *gofpdf.Fpdf, pageNumber, count int) {
	pdf.SetY(0)
	pdf.SetX(10)
	pdf.SetFont("Arial", "", 10)
	pdf.CellFormat(0, 10, fmt.Sprintf("%03d-%03d", count, pageNumber+1), "", 0, "L", false, 0, "")
}

func main() {

	// 获取当前目录下的所有 zip 文件
	files, err := ioutil.ReadDir(".")
	if err != nil {
		fmt.Println("读取目录错误:", err)
		os.Exit(1)
	}

	for _, file := range files {
		if file.IsDir() {
			continue
		}

		if strings.HasSuffix(file.Name(), ".zip") {
			// 对每个 zip 文件执行以下操作
			// 构建完整的文件路径
			zipPath := file.Name()
			// 创建解压目录，使用文件名作为目录名
			outputPath := strings.TrimSuffix(file.Name(), ".zip") + "_output"

			// 步骤 1：解压缩 zip 文件
			err := unzip(zipPath, outputPath)
			if err != nil {
				fmt.Printf("解压缩 %s 错误: %v\n", zipPath, err)
				continue
			}

			//步骤 2：将 TIF 文件转换为 PNG
			err = convertTIFtoPNG(outputPath)
			if err != nil {
				fmt.Printf("转换 TIF 到 PNG 时出错: %v\n", err)
				continue
			}

			// 步骤 3：读取并排序 PNG 文件
			pngFiles, err := readAndSortPNGs(outputPath)
			if err != nil {
				fmt.Printf("读取并排序 PNG 文件时出错: %v\n", err)
				continue
			}

			// 步骤 4：创建 PDF 文件
			pdfPath := strings.TrimSuffix(file.Name(), ".zip") + ".pdf"
			err = createPDF(pdfPath, pngFiles)
			if err != nil {
				fmt.Printf("创建 PDF 时出错: %v\n", err)
				continue
			}

			fmt.Printf("成功生成 PDF 文件: %s\n", pdfPath)

			err = os.RemoveAll(outputPath)
			if err != nil {
				fmt.Printf("删除临时文件出错: %v\n", err)
				continue
			}
		}
	}
}
